
import BaseService from "../service/BaseService";
import NetEvent from "../NetConfig";
import IServiceTarget from "../service/IServiceTarget";
import MessageHandler from "../handler/MessageHandler";
import { IRemoteProxyObserver } from "./IRemoteProxyObserver";
import GEvent from "../../cfw/event/GEvent";
// import GEvent from "../../cfw/event/GEvent";


/**
 * 发送失败应该再代理这边处理。
 */
export default class RemoteProxy implements IServiceTarget {

    //用到的服务
    protected service: BaseService;

    //消息的编解码器
    protected msgHandler: MessageHandler;


    // 连接次数
    protected connectCount: number = 0;


    protected connectTimeID: any;


    // 是否是主动断开的。
    private isActiveClose: boolean = false;

    protected observer: IRemoteProxyObserver;

    /**
     * 不同的服务可以使用相同的协议号
     * 发送数据后的缓存。
     */
    protected msgMap: { [session: number]: net.SendMessage } = {}

    //等待发送的小李列表
    protected waitList: net.SendMessage[] = []

    private session: number = 0;

    protected host: string;

    private beatTimeID: any = 0;

    constructor(host: string, msgHandler: MessageHandler, service: BaseService) {
        this.service = service;
        this.host = host;
        this.msgHandler = msgHandler;
        this.service.setTarget(this)
        // GEvent.instance().on(this.host, this.onSendMessage, this)
    }


    setObserver(obs: IRemoteProxyObserver) {
        this.observer = obs;
    }


    protected getSession() {
        this.session = this.session + 1;
        if (this.session > Number.MAX_SAFE_INTEGER - 1) {
            this.session = 1;
        }
        return this.session;
    }

    getState() {
        return this.service.getState();
    }




    getCloseFlag() {
        return this.isActiveClose;
    }




    isReady() {
        return this.service.isReady();
    }



    /**
     * 发送协议和返回协议映射表
     * @param map 
     */
    connect() {
        this.msgHandler.init();
        this.connectCount = 0;
        this.msgMap = {}
        this.destroy();
        this.isActiveClose = false;
        this.service.connect();


    }

    reConnect() {
        console.log(" this.connectCount ", this.connectCount);
        this.service.connect();
        this.connectCount++;
    }

    destroy() {
        this.isActiveClose = true;
        if (this.service.isReady()) {
            this.service.destroy();
        }
        if (this.beatTimeID) {
            clearInterval(this.beatTimeID);
            this.beatTimeID = null;
        }
    }


    sendBeat(func: Function, time: number = 3500) {
        if (this.beatTimeID) {
            clearInterval(this.beatTimeID);
            this.beatTimeID = null;
        }
        func();
        this.beatTimeID = setInterval(() => {
            func();
        }, time);
    }

    protected sendData(message: net.SendMessage) {
        if (message.session) {
            this.msgMap[message.session] = message;
        } else {
            this.msgMap[message.sendData.protoId] = message;
        }
        message.sendCount++;
        if (message.sendData.isBlock) {
            this.postMsgCount(1)
        }
        this.service.sendData(message);
    }


    onData(bytes: any) {
        let reciveData: net.ResData = this.msgHandler.decode(bytes);
        if (reciveData) {
            let session: number | string = reciveData.session;
            if (!session) {
                session = reciveData.protoId;
            }
            let sendMsg: net.SendMessage = this.msgMap[session]
            if (sendMsg) {
                reciveData.sendData = sendMsg.sendData;
                let list: net.PushData[] = reciveData.push
                if (list) {
                    for (let index = 0; index < list.length; index++) {
                        const element = list[index];
                        this.pushData(element)
                    }
                }
                if (sendMsg.sendData.callback) {
                    sendMsg.sendData.callback(reciveData.code, reciveData.data)
                }
                this.notifyData(reciveData)

                delete this.msgMap[session]
                if (sendMsg.sendData.isBlock) {
                    this.postMsgCount(-1)
                }
            } else {
                //推送
                let pushData: net.PushData = { protoId: reciveData.protoId, data: reciveData.data }
                this.pushData(pushData)
            }
        }
    }

    protected pushData(data: net.PushData) {
        // GEvent.instance().emit(this.host + NetEvent.PUSH_DATA, data)
        if (this.observer) {
            this.observer.onPush(data)
        }
    }

    protected notifyData(data: net.ResData) {
        if (this.observer) {
            this.observer.onData(data)
        }
        // GEvent.instance().emit(this.host + NetEvent.SEND_DATA, data)
    }

    onClose(data?: any) {


        console.log(" RemoteProxy onClose this.isActiveClose ", this.isActiveClose);
        if (this.isActiveClose) {
            this.isActiveClose = false;
            this.clearMsgCount()
            return;
        }

        this.connectTimeID = setTimeout(() => {

            this.reConnect();
            this.clear();
        }, 5000)


    }

    onError(data?: any) {
        //发送失败的情况未处理。
        // RemoteProxy.setMessageCount(0)

    }

    clear() {
        if (this.connectTimeID) {
            clearTimeout(this.connectTimeID);
            this.connectTimeID = null;
        }
    }
    onOpen(data?: any) {
        console.log("onOpen 1111111111111 ")
        this.clear();
        this.connectCount = 0;
        this.reSendData();
    }

    onSendMessage(param: net.SendData): void {
        let message: net.SendMessage = { sendData: param, session: this.getSession(), sendCount: 0 }
        this.msgHandler.encode(message);
        if (this.isReady()) {
            this.sendData(message)
        } else {
            this.pushToWait(message)
            this.connect()
        }
    }

    //如果是长连接 就是链接失败，如果是短链接就是发送消息失败
    reSendData(): void {
        while (this.waitList.length > 0) {
            let msg = this.waitList.shift()
            this.sendData(msg)
        }
    }

    pushToWait(message: net.SendMessage) {
        this.waitList.push(message)
    }


    reSendMessage() {

    }


    private static messageCount: number = 0;
    protected msgCount: number = 0;

    private postMsgCount(n: number) {
        this.msgCount += n;
        RemoteProxy.updateMessageCount(n)
    }

    private clearMsgCount() {
        this.postMsgCount(-this.msgCount)
    }

    private static setMessageCount(n: number) {
        this.messageCount = n;
        GEvent.instance().emit(NetEvent.UPDATE_SEND_MESSAGE_COUNT, this.messageCount)
    }

    private static updateMessageCount(num: number) {
        this.messageCount += num;
        if (num < 0 && this.messageCount < 0) {
            this.messageCount = 0;
        }
        this.setMessageCount(this.messageCount)
    }
}
